package com.sip.executionadapter.manager;

import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

import com.sip.dbadapter.dao.domain.ApiDefinition;
import com.sip.dbadapter.dao.domain.ScanTypeRest;
import com.sip.dbadapter.dao.domain.ScenarioRecord;
import com.sip.dbadapter.dao.interfaces.RestServiceDao;
import com.sip.dbadapter.dao.utility.DaoLoadFactory;
import com.sip.dbadapter.dao.utility.DaoNameConstant;
import com.sip.dbadapter.domain.registry.DomainRegistry;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

/**
 * Class has written to handle jersey client call. Class call dao itself and
 * make jersey client call successful.
 * 
 * @author da40188
 */
public class JerseyExecutionManager {
    private static final Logger logger = Logger.getLogger(JerseyExecutionManager.class);
    private Client client = null;

    private JerseyExecutionManager() {
        BasicConfigurator.configure();
        if (null == client) {
            client = Client.create();
        }
    }

    public static JerseyExecutionManager createInstance() {

        return new JerseyExecutionManager();
    }

    public void invoke(final Map<String, Object> domainMap) throws Exception {

        final ApiDefinition apiDefinitionDomainObj = (ApiDefinition) domainMap.get(DomainRegistry.API_DEFINITION);
        final ScenarioRecord scenarioRecordDomainObj = (ScenarioRecord) domainMap.get(DomainRegistry.SCENARIO_RECORD);
        final ScanTypeRest scanTypeRestDomainObj = (ScanTypeRest) domainMap.get(DomainRegistry.SCAN_TYPE_REST);
        final Map<String, String> httpHeaders = (Map<String, String>) domainMap
                .get(DomainRegistry.DOMAIN_RELATED_GENERIC_INFO);

        final String packageHierachy = apiDefinitionDomainObj.getPackageHierachy();
        final ScanTypeRest scanTypeRestDomain = getScanTypeRestDomain(apiDefinitionDomainObj.getApiId());

        final String acceptType = scanTypeRestDomain.getMethodAction();
        String url = null;

        if (!("/".equals(scanTypeRestDomain.getResourceBase().substring(
                scanTypeRestDomain.getResourceBase().length() - 1)))
                && !packageHierachy.startsWith("/"))
            url = scanTypeRestDomainObj.getResourceBase() + "/" + packageHierachy;
        else {
            url = scanTypeRestDomainObj.getResourceBase() + packageHierachy;
        }

        final WebResource webResource = client.resource(url);

        if (null != httpHeaders && !httpHeaders.isEmpty()) {
            for (Entry<String, String> header : httpHeaders.entrySet()) {
                webResource.header(header.getKey(), header.getValue());
            }
        }

        System.out.println("##################### RESOURCE URL ##################### > ");
        System.out.println(url);
        System.out.println("##################### INPUT JSON STRING ##################### > ");
        System.out.println(scenarioRecordDomainObj.getConsumeValue());

        if (acceptType.equalsIgnoreCase("GET")) {

            final String result = doGET(webResource);
            scenarioRecordDomainObj.setResult(result);

        } else if (acceptType.equalsIgnoreCase("POST")) {

            final String result = doPOST(webResource, scenarioRecordDomainObj.getConsumeValue());
            scenarioRecordDomainObj.setResult(result);

        } else if (acceptType.equalsIgnoreCase("PUT")) {

            final String result = doPUT(webResource, scenarioRecordDomainObj.getConsumeValue());
            scenarioRecordDomainObj.setResult(result);
        } else if (acceptType.equalsIgnoreCase("DELETE")) {

            final String result = doDELETE(webResource, scenarioRecordDomainObj.getConsumeValue());
            scenarioRecordDomainObj.setResult(result);
        }

        domainMap.put(DomainRegistry.SCENARIO_RECORD, scenarioRecordDomainObj);
        System.out.println("##################### OUTPUT JSON STRING ##################### > ");
        System.out.println(scenarioRecordDomainObj.getResult());
    }

    private String doGET(final WebResource webResource) {

        final ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);

        final String output = response.getEntity(String.class);

        return output;
    }

    private String doPOST(final WebResource webResource, final String input) {

        final ClientResponse response = webResource.type("application/json").post(ClientResponse.class, input);

        int responseCode = response.getStatus();

        String output = null;

        if (ClientResponse.Status.NO_CONTENT.getStatusCode() == responseCode) { // success
                                                                                // and
                                                                                // no
                                                                                // response
            output = "{}";
        } else { // success with response | business exceptions(include 500-
                 // unknow exceptions)
            output = response.getEntity(String.class);
        }

        return output;
    }

    private String doPUT(final WebResource webResource, final String input) {

        final ClientResponse response = webResource.type("application/json").put(ClientResponse.class, input);

        int responseCode = response.getStatus();

        String output = null;

        if (ClientResponse.Status.NO_CONTENT.getStatusCode() == responseCode) { // success
                                                                                // and
                                                                                // no
                                                                                // response
            output = "{}";
        } else { // success with response | business exceptions(include 500-
                 // unknow exceptions)
            output = response.getEntity(String.class);
        }

        return output;

    }

    private String doDELETE(final WebResource webResource, final String input) {

        final ClientResponse response = webResource.type("application/json").delete(ClientResponse.class);

        int responseCode = response.getStatus();

        String output = null;

        if (ClientResponse.Status.NO_CONTENT.getStatusCode() == responseCode) { // success
                                                                                // and
                                                                                // no
                                                                                // response
            output = "{}";
        } else { // success with response | business exceptions(include 500-
                 // unknow exceptions)
            output = response.getEntity(String.class);
        }

        return output;

    }

    private ScanTypeRest getScanTypeRestDomain(final Long apiId) throws Exception {

        // TODO : Dao call implementation.
        final RestServiceDao restServiceDao = (RestServiceDao) DaoLoadFactory.getDao(DaoNameConstant.GET_REST_URL);
        final ScanTypeRest scanTypeRestDomain = restServiceDao.getRestServiceByApiId(apiId);
        return scanTypeRestDomain;

    }

}
